﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PlaceHR.Processor.Processor.Salary.Steps
{
    class SickLeaveSalaryStepCalculator : StepCalculatorBase<SalaryProcessorContext, EmployeeSalary>
    {
        public override void Calculate(SalaryProcessorContext salaryProcessorContext, EmployeeSalary employeeSalary)
        {
            DateTime monthFirstDay = new DateTime(salaryProcessorContext.CurrentEngine.Year, salaryProcessorContext.CurrentEngine.Month, 1);
            DateTime monthLastDay = monthFirstDay.AddMonths(1).AddDays(-1);
            var sickLeave = salaryProcessorContext.CurrentEmployee.EmployeeVacation.Where(p => !p.IsDeleted
                && p.VacationTypeCode.Equals("SKL", StringComparison.OrdinalIgnoreCase)
                && !p.Status.Equals("Denied", StringComparison.OrdinalIgnoreCase)
                && p.FromTime.HasValue
                && p.FromTime.Value <= monthLastDay
                && p.EndTime.HasValue
                && p.EndTime.Value >= monthFirstDay).ToList();

            decimal vacationHours = 0;
            if (sickLeave != null && sickLeave.Count > 0)
            {
                foreach (var item in sickLeave)
                {
                    //如果该假期全程位于本月内，则时间全部累计
                    if (item.FromTime.Value.Month == salaryProcessorContext.CurrentEngine.Month && item.EndTime.Value.Month == salaryProcessorContext.CurrentEngine.Month)
                    {
                        vacationHours = vacationHours + item.Length.GetValueOrDefault(0);
                    }

                    //如果该假期起始日期在本月之前
                    else if (item.FromTime.Value.Year < salaryProcessorContext.CurrentEngine.Year
                        || (item.FromTime.Value.Year == salaryProcessorContext.CurrentEngine.Year && item.FromTime.Value.Month < salaryProcessorContext.CurrentEngine.Month))
                    {
                        //如果结束时间超出本月，则说明假期贯穿了本月，本月全部请假
                        if (item.EndTime.Value.Year > salaryProcessorContext.CurrentEngine.Year || item.EndTime.Value.Month > salaryProcessorContext.CurrentEngine.Month)
                        {
                            vacationHours = vacationHours + salaryProcessorContext.WorkingDaysPerMonth * salaryProcessorContext.WorkingHoursPerDay;
                        }
                        //否则，说明假期在本月内结束，那么计算本月一号起至结束日的时间在整个假期中所占比例
                        //注：这里无法利用时间差计算，因为中间的日子涉及到周末，放假等，无法核算
                        else
                        {
                            var percent = item.EndTime.Value.Day / (item.EndTime.Value - item.FromTime.Value).TotalDays;
                            vacationHours = vacationHours + item.Length.GetValueOrDefault() * (decimal)percent;
                        }
                    }

                    //如果该假期结束日期在本月之后，则只计算假期起始日到本月末的时间在整个假期中所占比例
                    else if (item.EndTime.Value.Year > salaryProcessorContext.CurrentEngine.Year
                        || (item.EndTime.Value.Year == salaryProcessorContext.CurrentEngine.Year && item.EndTime.Value.Month > salaryProcessorContext.CurrentEngine.Month))
                    {
                        var totalDaysThisMonth = (monthFirstDay.AddMonths(1) - monthFirstDay).TotalDays;
                        var percent = (totalDaysThisMonth - item.FromTime.Value.Day + 1) / (item.EndTime.Value - item.FromTime.Value).TotalDays;

                        vacationHours = vacationHours + item.Length.GetValueOrDefault() * (decimal)percent;
                    }
                }
            }

            if (vacationHours > 0)
            {
                decimal totalSalary = (employeeSalary.BasicSalary ?? 0)
                                         + (employeeSalary.PositionSalary ?? 0)
                                         + (employeeSalary.Others ?? 0)
                                         + (employeeSalary.Bonus ?? 0);
                decimal sickSalary = 0;
                if (salaryProcessorContext.CurrentSickSalarySettingList != null && salaryProcessorContext.CurrentSickSalarySettingList.Count > 0)
                {
                    sickSalary = this.GetSickSalary(salaryProcessorContext, totalSalary, vacationHours);
                }

                //这里得到病假那些天需要扣除的工资
                employeeSalary.SickLeave = ((totalSalary - sickSalary) / salaryProcessorContext.WorkingDaysPerMonth) * (vacationHours / salaryProcessorContext.WorkingHoursPerDay);
            }

        }


        private decimal GetSickSalary(SalaryProcessorContext salaryProcessorContext, decimal totalSalary, decimal vacationHours)
        {
            decimal sickSalary = 0;
            short workAge = salaryProcessorContext.CurrentEmployee.WorkingAge ?? 0;
            bool belowSixMonth = vacationHours/salaryProcessorContext.WorkingHoursPerDay < salaryProcessorContext.WorkingDaysPerMonth * 6;
            var setting = salaryProcessorContext.CurrentSickSalarySettingList.First(p => p.UnderSixMonth == belowSixMonth
                && ((p.MinWorkAge == null && p.MaxWorkAge.Value > workAge) || (p.MaxWorkAge == null && p.MinWorkAge.Value <= workAge)
                        || (p.MinWorkAge.Value <= workAge && p.MaxWorkAge.Value > workAge)));
            
            if (setting != null)
            {
                sickSalary = totalSalary * setting.SalaryPercent.Value / 100;
            }

            if (salaryProcessorContext.CurrentSickSalaryRestriction.CheckCityAverageSalary 
                && salaryProcessorContext.CurrentSickSalaryRestriction.CityAverageSalaryPercent != null
                && sickSalary > salaryProcessorContext.AverageSalary * salaryProcessorContext.CurrentSickSalaryRestriction.CityAverageSalaryPercent.Value)
            {
                sickSalary = salaryProcessorContext.AverageSalary;
            }

            if (salaryProcessorContext.CurrentSickSalaryRestriction.CheckBaseSalary
                && salaryProcessorContext.CurrentSickSalaryRestriction.BaseSalaryPercent != null
                && sickSalary < totalSalary * salaryProcessorContext.CurrentSickSalaryRestriction.BaseSalaryPercent.Value)
            {
                sickSalary = totalSalary * salaryProcessorContext.CurrentSickSalaryRestriction.BaseSalaryPercent.Value;
            }

            if (salaryProcessorContext.CurrentSickSalaryRestriction.CheckMinimumWage
                && salaryProcessorContext.CurrentSickSalaryRestriction.MinimumWagePercent != null
                && sickSalary < totalSalary * salaryProcessorContext.CurrentSickSalaryRestriction.MinimumWagePercent.Value)
            {
                sickSalary = totalSalary * salaryProcessorContext.CurrentSickSalaryRestriction.MinimumWagePercent.Value;
            }

            return sickSalary;
        }

    }
}
